package com.xbongbong.paas.script.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.ext.FieldPermissionEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateNodeEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.model.PaasProcessDataModel;
import com.xbongbong.paas.model.PaasProcessTaskModel;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.model.PaasProcessTemplateNodeModel;
import com.xbongbong.paas.pojo.dto.FixDataJobDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractOutstockEnum;
import com.xbongbong.saas.enums.business.PurchaseInstockEnum;
import com.xbongbong.saas.enums.business.RefundInstockEnum;
import com.xbongbong.saas.enums.business.ReturnedPurchaseOutstockEnum;
import com.xbongbong.saas.enums.business.WorkOrderOutstockEnum;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.sys.model.CompanyModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.xbongbong.saas.enums.XbbRefTypeEnum.WORK_ORDER_OUTSTOCK;

/**
 * @Program xbb-pro
 * @Description 流程相关的脚本
 * @Author caoyy
 * @Date 2019/12/3
 **/
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/script/process")
public class ProcessTemplateScriptController {
    private static final Logger LOG = LoggerFactory.getLogger(ProductScriptController.class);
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private PaasProcessTemplateNodeModel paasProcessTemplateNodeModel;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasProcessDataModel paasProcessDataModel;
    @Resource
    private ProductModel productModel;
    @Resource
    private PaasProcessTaskModel paasProcessTaskModel;
    /**
    * @Description: 将业务拆分前的流程设置拷贝一份
    * @Param: [fixDataJobDTO, br]
    * @return: java.lang.String
    * @Author: cyy
    * @Date: 2019/12/3
    */
    @RequestMapping(value = "/copyTemplate", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String copyProcessTemplate(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = companyModel.getCorpidList();
        }
        Integer businessType = fixDataJobDTO.getBusinessType();
        if (Objects.isNull(businessType)){
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(),"业务类型没传");
        } else {
            if (businessType != XbbRefTypeEnum.OTHER_INSTOCK.getCode() && businessType != XbbRefTypeEnum.OTHER_OUTSTOCK.getCode()){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(),"业务类型不对，请传入1406或者1506");
            }
        }
        LOG.warn("数据库中共有公司" + corpidList.size() + "家");
        Integer corpidCount = 0;
        List<Integer> INSTOCK_TYPE_LIST = Arrays.asList(XbbRefTypeEnum.PURCHASE_INSTOCK.getCode(), XbbRefTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode(), XbbRefTypeEnum.REFUND_INSTOCK.getCode(), XbbRefTypeEnum.PRODUCTION_INSTOCK.getCode());
        List<Integer> OUTSTOCK_TYPE_LIST = Arrays.asList(XbbRefTypeEnum.CONTRACT_OUTSTOCK.getCode(), XbbRefTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode(),XbbRefTypeEnum.PRODUCTION_MATERIEL_OUTSTOCK.getCode(), WORK_ORDER_OUTSTOCK.getCode());
        List<Integer> dictEnum = businessType == XbbRefTypeEnum.OTHER_INSTOCK.getCode() ? INSTOCK_TYPE_LIST : OUTSTOCK_TYPE_LIST;
        for (String corpid : corpidList) {
            ++ corpidCount;
            LOG.warn("公司" + corpidCount + "/" + corpidList.size());
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(ParameterConstant.CORPID, corpid);
            param.put("businessType", businessType);
            param.put("orderByStr", " version_id DESC ");
            List<PaasProcessTemplateEntityExt> processList = paasProcessTemplateModel.list(param);
            if (processList.size() >= 20) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_SIZE_MAX_LIMIT);
            }
            for (int i = 0; i < dictEnum.size(); i++) {
                Integer type = dictEnum.get(i);

                param.clear();
                param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
                param.put(ParameterConstant.CORPID, corpid);
                param.put("businessType", type);
                param.put("orderByStr", " version_id DESC ");
                List<PaasProcessTemplateEntityExt> processArray = paasProcessTemplateModel.list(param);
                if (CollectionsUtil.isNotEmpty(processArray)){
                    LOG.warn("公司id：" + corpid + "业务类型：" + type + "已存在流程模板,刷下一个业务");
                    continue;
                }
                XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(type);
                PaasFormExplainEntity explainEntity = paasFormExplainModel.getByBusinessType(type,corpid);
                if (Objects.isNull(explainEntity)){
                    continue;
                }
                Long appId = explainEntity.getAppId();
                Long menuId = explainEntity.getMenuId();
                Long newFormId = paasFormModel.getFormIdByBusinessType(corpid,type);
                processList.forEach(item -> {
                    Long oldTempId = item.getId();
                    item.setId(null);
                    item.setAppId(appId);
                    item.setFormId(newFormId);
                    item.setBusinessType(xbbRefTypeEnum.getCode());
                    item.setMenuId(menuId);
                    paasProcessTemplateModel.insert(item);
                    Long newTempId = item.getId();
                    param.clear();
                    param.put("corpid", corpid);
                    param.put("del", 0);
                    param.put("templateId", oldTempId);
                    Integer totalCount = paasProcessTemplateNodeModel.getEntitysCount(param);

                    int pageSize = 500;
                    int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize) + 1;
                    int lastPageSize = (totalCount % pageSize == 0) ? pageSize : (totalCount % pageSize);
                    for (int page = 0; page < totalPage; page++) {
                        if (page == totalPage - 1) {
                            param.put("pageNum", lastPageSize);
                        } else {
                            param.put("pageNum", pageSize);
                        }
                        param.put("start", page * pageSize);
                        LOG.warn("第" + page + "页开始");
                        List<PaasProcessTemplateNodeEntityExt> paasProcessTemplateNodeEntityExtList = paasProcessTemplateNodeModel.list(param);
                        if (paasProcessTemplateNodeEntityExtList.isEmpty()) {
                            continue;
                        }

                        paasProcessTemplateNodeEntityExtList.forEach(entityExt -> {
                            entityExt.setId(null);
                            entityExt.setAppId(appId);
                            entityExt.setTemplateId(newTempId);
                            entityExt.setFormId(newFormId);
                            entityExt.setMenuId(menuId);

                            // 审批流程默认权限
                            List<FieldPermissionEntityExt> appendFieldPermissionList = new ArrayList<>();
                            switch (xbbRefTypeEnum){
                                case WORK_ORDER_OUTSTOCK:
                                    FieldPermissionEntityExt linkCustomer = new FieldPermissionEntityExt(WorkOrderOutstockEnum.LINK_CUSTOMER.getAttr(),WorkOrderOutstockEnum.LINK_CUSTOMER.getFieldType(),0,1,0);
                                    FieldPermissionEntityExt linkContact = new FieldPermissionEntityExt(WorkOrderOutstockEnum.LINK_CONTACT.getAttr(),WorkOrderOutstockEnum.LINK_CONTACT.getFieldType(),0,1,0);
                                    FieldPermissionEntityExt customerPhone = new FieldPermissionEntityExt(WorkOrderOutstockEnum.CUSTOMER_PHONE.getAttr(),WorkOrderOutstockEnum.CUSTOMER_PHONE.getFieldType(),0,1,0);
                                    FieldPermissionEntityExt customerPhoneType = new FieldPermissionEntityExt(WorkOrderOutstockEnum.CUSTOMER_PHONE.getAttr(),"text_1",WorkOrderOutstockEnum.CUSTOMER_PHONE.getFieldType(),0,1,0);
                                    FieldPermissionEntityExt customerPhoneValue = new FieldPermissionEntityExt(WorkOrderOutstockEnum.CUSTOMER_PHONE.getAttr(),"text_2",WorkOrderOutstockEnum.CUSTOMER_PHONE.getFieldType(),0,1,0);
                                    FieldPermissionEntityExt address = new FieldPermissionEntityExt(WorkOrderOutstockEnum.CUSTOMER_ADDRESS.getAttr(),WorkOrderOutstockEnum.CUSTOMER_ADDRESS.getFieldType(),0,1,0);
                                    appendFieldPermissionList.addAll(Arrays.asList(linkCustomer,linkContact,customerPhone,customerPhoneType,customerPhoneValue,address));
                                    break;
                                case CONTRACT_OUTSTOCK:
                                    FieldPermissionEntityExt linkCustomer2 = new FieldPermissionEntityExt(ContractOutstockEnum.LINK_CUSTOMER.getAttr(),ContractOutstockEnum.LINK_CUSTOMER.getFieldType(),0,1,0);
                                    FieldPermissionEntityExt customerPhone2 = new FieldPermissionEntityExt(ContractOutstockEnum.CUSTOMER_PHONE.getAttr(),ContractOutstockEnum.CUSTOMER_PHONE.getFieldType(),0,1,0);
                                    FieldPermissionEntityExt customerPhone2Type = new FieldPermissionEntityExt(ContractOutstockEnum.CUSTOMER_PHONE.getAttr(),"text_1",ContractOutstockEnum.CUSTOMER_PHONE.getFieldType(),0,1,0);
                                    FieldPermissionEntityExt customerPhone2Value = new FieldPermissionEntityExt(ContractOutstockEnum.CUSTOMER_PHONE.getAttr(),"text_2",ContractOutstockEnum.CUSTOMER_PHONE.getFieldType(),0,1,0);
                                    FieldPermissionEntityExt address2 = new FieldPermissionEntityExt(ContractOutstockEnum.CUSTOMER_ADDRESS.getAttr(),ContractOutstockEnum.CUSTOMER_ADDRESS.getFieldType(),0,1,0);
                                    appendFieldPermissionList.addAll(Arrays.asList(linkCustomer2,customerPhone2,customerPhone2Type,customerPhone2Value,address2));
                                    break;
                                case RETURNED_PURCHASE_OUTSTOCK:
                                    FieldPermissionEntityExt linkSupplier = new FieldPermissionEntityExt(ReturnedPurchaseOutstockEnum.LINK_SUPPLIER.getAttr(),ReturnedPurchaseOutstockEnum.LINK_SUPPLIER.getFieldType(),0,1,0);
                                    appendFieldPermissionList.addAll(Arrays.asList(linkSupplier));
                                    break;
                                case PURCHASE_INSTOCK:
                                    FieldPermissionEntityExt supplierId = new FieldPermissionEntityExt(PurchaseInstockEnum.SUPPLIER_ID.getAttr(),PurchaseInstockEnum.SUPPLIER_ID.getFieldType(),0,1,0);
                                    appendFieldPermissionList.addAll(Arrays.asList(supplierId));
                                    break;
                                case REFUND_INSTOCK:
                                    FieldPermissionEntityExt customerId2 = new FieldPermissionEntityExt(RefundInstockEnum.CUSTOMER_ID.getAttr(),RefundInstockEnum.CUSTOMER_ID.getFieldType(),0,1,0);
                                    appendFieldPermissionList.addAll(Arrays.asList(customerId2));
                                    break;

                                default:
                                    break;
                            }
                            List<FieldPermissionEntityExt> fieldPermissionList = entityExt.getFieldPermissionList();
                            fieldPermissionList.addAll(appendFieldPermissionList);
                            entityExt.setFieldPermission(JSON.toJSONString(fieldPermissionList));

                        });

                        paasProcessTemplateNodeModel.insertBatch(paasProcessTemplateNodeEntityExtList);
                        LOG.warn("第" + page + "页结束");
                    }
                });
            }
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("copyTemplate 操作成功");
        return null;
    }

    /**
    * @Description:将审批中的入库单 出库单类型复制到外面来
    * @Param: [fixDataJobDTO, br] 
    * @return: java.lang.String 
    * @Author: cyy 
    * @Date: 2019/12/5 
    */ 
    @RequestMapping(value = "/copyProcessType", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String copyProcessType(@RequestBody @Valid FixDataJobDTO fixDataJobDTO,  BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = companyModel.getCorpidList();
        }
        LOG.warn("数据库中共有公司" + corpidList.size() + "家");
        Integer index = 1;
        for (String corpid : corpidList) {
            LOG.warn(index + "/" + corpidList.size());
            index ++;
           Map<String,Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(ParameterConstant.CORPID,corpid);
            params.put(ParameterConstant.DEL,DelEnum.NORMAL.getDel());
            params.put("businessTypeIn",Arrays.asList(XbbRefTypeEnum.OTHER_INSTOCK.getCode(),XbbRefTypeEnum.OTHER_OUTSTOCK.getCode()));
            Integer totalCount = paasProcessDataModel.getEntitysCount(params);
            LOG.warn("corpid:" + corpid + "数据库中共有审批数据" + totalCount + "条数据");
            int pageSize = 500;
            int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize) + 1;
            int lastPageSize = (totalCount % pageSize == 0) ? pageSize : (totalCount % pageSize);
            for (int page = 0; page < totalPage; page++) {
                //设置分页
                if (page == totalPage - 1) {
                    params.put("pageNum", lastPageSize);
                } else {
                    params.put("pageNum", pageSize);
                }
                params.put("start", page * pageSize);
                LOG.warn("第" + page + "页开始");
                List<PaasProcessDataEntity> paasProcessDataEntityList = paasProcessDataModel.list(params);
                if (paasProcessDataEntityList.isEmpty()) {
                    continue;
                }
                List<UpdateDataEntity> updateDataEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                List<UpdateDataEntity> updateTaskEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                paasProcessDataEntityList.forEach(item -> {
                    JSONObject data = JSONObject.parseObject(item.getData());
                    UpdateDataEntity updateDataEntity = new UpdateDataEntity();
                    UpdateDataEntity updateTaskEntity = new UpdateDataEntity();
                    updateDataEntity.setCorpid(corpid);
                    updateDataEntity.setId(item.getId());
                    updateDataEntity.setDel(DelEnum.NORMAL.getDel());
                    if (Objects.isNull(item.getStockType())){
                        // 老数据
                        updateDataEntity.setStockType(data.getInteger("text_3") == null ? null : data.getInteger("text_3"));
                    } else {
                        // 新数据
                        updateDataEntity.setStockType(item.getStockType());
                    }
                    updateTaskEntity.setId(item.getTaskId());
                    updateTaskEntity.setCorpid(corpid);
                    updateTaskEntity.setDel(DelEnum.NORMAL.getDel());
                    updateTaskEntity.setStockType(data.getInteger("text_3"));
                    updateDataEntityList.add(updateDataEntity);
                    updateTaskEntityList.add(updateTaskEntity);
                });
                if (CollectionsUtil.isNotEmpty(updateDataEntityList)) {
                    paasProcessDataModel.updateInstockAndOutstockType(updateDataEntityList);
                }
                if (CollectionsUtil.isNotEmpty(updateTaskEntityList)) {
                    paasProcessTaskModel.updateInstockAndOutstockType(updateTaskEntityList);
                }
                LOG.warn("corpid:" + corpid + "数据库中共有产品" + totalCount + "条数据" + "总共有" + totalPage + "页" + "已更新至第" + page + "页");
            }
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        return null;
    }
}
